
package com.hlkj.pay.app.devices.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.pojo.LocalRequest;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.common.IUploadService;
import com.hlkj.pay.app.devices.IMerchantQrAppService;
import com.hlkj.pay.app.openapi.IOpenApiAppService;
import com.hlkj.pay.app.order.IPayOrderAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.dto.LocalAdminUserRequest;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.devices.MerchantQrDO;
import com.hlkj.pay.infrastructure.model.devices.MerchantQrSetDO;
import com.hlkj.pay.infrastructure.model.devices.MerchantQrTemplateDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppDO;
import com.hlkj.pay.service.devices.IMerchantQrService;
import com.hlkj.pay.service.devices.IMerchantQrTemplateService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.util.OrderCodeUtil;
import com.hlkj.pay.vo.devices.req.MerchantQrBindReq;
import com.hlkj.pay.vo.devices.req.MerchantQrListReq;
import com.hlkj.pay.vo.devices.req.MerchantQrSetReq;
import com.hlkj.pay.vo.devices.req.MerchantQrUpdateReq;
import com.hlkj.pay.vo.merchant.req.UpdateStatusReq;
import com.hlkj.pay.vo.openapi.order.resp.PayOrderSubmitApiResp;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;
import com.hlkj.pay.vo.order.req.PayOrderParamReq;
import com.hlkj.pay.vo.order.req.QrOrderParamReq;

import cn.hutool.extra.servlet.ServletUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2025/01/20 11:11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantQrAppService implements IMerchantQrAppService {

    private final IMerchantQrService merchantQrService;

    private final IMerchantQrTemplateService merchantQrTemplateService;

    private final IMerchantApplicationService merchantApplicationService;

    private final IUploadService uploadService;

    private final IOpenApiAppService openApiAppService;

    private final IPayOrderAppService payOrderAppService;

    private final OrderCodeUtil orderCodeUtil;

    private final IMerchantService merchantService;

    @Override
    public CommonResult<Void> saveQr(MerchantQrSetReq merchantQrSetReq) {
        log.info("saveQr merchantQrSetReq:{}", JsonUtils.toJsonString(merchantQrSetReq));
        try {
            MerchantQrTemplateDO merchantQrTemplate = merchantQrTemplateService.queryDetail(merchantQrSetReq.getTemplateId());
            if (merchantQrTemplate == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            List<MerchantQrDO> merchantQrList = new ArrayList<>();
            for (MerchantQrListReq merchantQrListReq : merchantQrSetReq.getMerchantQrListReqs()) {
                MerchantQrDO merchantQrDO = new MerchantQrDO();
                merchantQrDO.setCode(merchantQrListReq.getCode());
                merchantQrDO.setBatchNo(merchantQrSetReq.getBatchNo());
                merchantQrDO.setStatus(merchantQrSetReq.getStatus());
                // merchantQrDO.setAppId();
                merchantQrDO.setAmountLimit(merchantQrSetReq.getAmountLimit());
                merchantQrDO.setAmount(merchantQrSetReq.getAmount());
                merchantQrDO.setSubType(merchantQrSetReq.getSubType());
                if (StringUtils.hasText(merchantQrListReq.getCodeUrl())) {
                    merchantQrDO.setCodeUrl(merchantQrListReq.getCodeUrl());
                    merchantQrDO.setQrUrl(merchantQrListReq.getQrUrl());
                }
                else {
                    if (StringUtils.hasText(merchantQrListReq.getCodeBase64())) {
                        byte[] imageBytes = Base64.getDecoder().decode(merchantQrListReq.getCodeBase64());
                        CommonResult<String> commonResult = uploadService.upload(imageBytes, CommonEnum.OssEnum.IMAGE);
                        merchantQrDO.setCodeUrl(commonResult.getData());
                    }
                }
                LocalRequest localRequest = LocalContext.get();
                if (localRequest != null && localRequest instanceof LocalAdminUserRequest) {
                    merchantQrDO.setSn(localRequest.getSn());
                }
                merchantQrList.add(merchantQrDO);
            }
            MerchantQrSetDO merchantQrSetDO = new MerchantQrSetDO();
            merchantQrSetDO.setBatchNo(merchantQrSetReq.getBatchNo());
            merchantQrSetDO.setStatus(merchantQrSetReq.getStatus());
            merchantQrSetDO.setTemplateId(merchantQrSetReq.getTemplateId());
            merchantQrSetDO.setNum(merchantQrSetReq.getNum());
            merchantQrSetDO.setAmountLimit(merchantQrSetReq.getAmountLimit());
            merchantQrSetDO.setAmount(merchantQrSetReq.getAmount());
            merchantQrSetDO.setPageType(merchantQrSetReq.getPageType());
            merchantQrSetDO.setPageUrl(merchantQrSetReq.getPageUrl());
            merchantQrSetDO.setSubType(merchantQrSetReq.getSubType());
            merchantQrService.addMerchantQr(merchantQrSetDO, merchantQrList);
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("saveTemplate error:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateQr(MerchantQrUpdateReq merchantQrUpdateReq) {
        log.info("updateQr merchantQrUpdateReq:{}", JsonUtils.toJsonString(merchantQrUpdateReq));
        try {
            MerchantQrDO merchantQr = merchantQrService.queryDetail(merchantQrUpdateReq.getCode());
            if (merchantQr == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            MerchantQrDO merchantQrDO = new MerchantQrDO();
            merchantQrDO.setId(merchantQr.getId());
            merchantQrDO.setStatus(merchantQrUpdateReq.getStatus());
            merchantQrDO.setAmountLimit(merchantQrUpdateReq.getAmountLimit());
            merchantQrDO.setAmount(merchantQrUpdateReq.getAmount());
            merchantQrDO.setSubType(merchantQrUpdateReq.getSubType());
            merchantQrService.updateMerchantQr(merchantQrDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("updateQr error:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> bindQr(MerchantQrBindReq merchantQrBindReq) {
        log.info("bindQr merchantQrBindReq:{}", JsonUtils.toJsonString(merchantQrBindReq));
        try {
            MerchantQrDO merchantQr = merchantQrService.queryDetail(merchantQrBindReq.getCode());
            if (merchantQr == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(merchantQrBindReq.getAppId());
            if (merchantAppDO == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            MerchantQrDO merchantQrDO = new MerchantQrDO();
            merchantQrDO.setId(merchantQr.getId());
            merchantQrDO.setBindStatus(1);
            merchantQrDO.setAppId(merchantQrBindReq.getAppId());
            merchantQrDO.setSn(merchantAppDO.getSn());
            merchantQrDO.setCodeUrl(merchantQrBindReq.getCodeUrl());
            merchantQrDO.setQrUrl(merchantQrBindReq.getQrUrl());
            merchantQrService.updateMerchantQr(merchantQrDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("bindQr error:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateStatus(UpdateStatusReq updateStatusReq) {
        log.info("updateStatus updateStatusReq:{}", JsonUtils.toJsonString(updateStatusReq));
        try {
            MerchantQrDO merchantQr = merchantQrService.queryDetail(updateStatusReq.getCode());
            if (merchantQr == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            MerchantQrDO merchantQrDO = new MerchantQrDO();
            merchantQrDO.setId(merchantQr.getId());
            merchantQrDO.setStatus(updateStatusReq.getStatus());
            merchantQrService.updateMerchantQr(merchantQrDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("updateStatus error:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<PayOrderSubmitApiResp> submitOrder(QrOrderParamReq qrOrderParamReq) {
        log.info("submitOrder qrOrderParamReq:{}", JsonUtils.toJsonString(qrOrderParamReq));
        // 获取当前登录人信息
        LocalAdminUserRequest localAdminUserRequest = (LocalAdminUserRequest) LocalContext.get();
        try {
            MerchantQrDO merchantQr = merchantQrService.queryDetail(qrOrderParamReq.getCode());
            if (merchantQr == null) {
                return CommonResult.error(OpenApiResultCode.DATA_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantQr.getAmountLimit())) {
                if (!StringUtils.hasText(qrOrderParamReq.getAmount())) {
                    return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
                }
            }
            else {
                qrOrderParamReq.setAmount(MerchantUtils.bigDecimalToString2(merchantQr.getAmount()));
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantQr.getStatus())) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EFFECT);
            }
            CommonResult<Void> voidCommonResult = openApiAppService.setAppInfo(merchantQr.getAppId());
            if (!voidCommonResult.isSuccess()) {
                // 从新设置登录人信息
                LocalContext.set(localAdminUserRequest);
                return CommonResult.error(voidCommonResult.getCode(), voidCommonResult.getMsg());
            }
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            PayOrderParamReq payOrderParamReq = new PayOrderParamReq();
            payOrderParamReq.setSceneType(1);
            if (StringUtils.hasText(qrOrderParamReq.getPaySubType())) {
                payOrderParamReq.setPaySubType(qrOrderParamReq.getPaySubType());
            }
            else {
                payOrderParamReq.setPaySubType(merchantQr.getSubType());
            }
            payOrderParamReq.setPayType(PayEnums.PAY_TYPE.fromByCode(qrOrderParamReq.getPayType()).getType());
            payOrderParamReq.setMchOrderNo(orderCodeUtil.orderNo(PayOrderEnums.ORDER_NO_TYPE.RECHARGE_APPLY));
            payOrderParamReq.setAmount(qrOrderParamReq.getAmount());
            payOrderParamReq.setClientIp(ServletUtil.getClientIP(request, null));
            if (StringUtils.hasText(qrOrderParamReq.getRemark())) {
                payOrderParamReq.setSubject(qrOrderParamReq.getRemark());
                payOrderParamReq.setDescription(qrOrderParamReq.getRemark());
            }
            else {
                // MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(merchantQr.getSn());
                // if (StringUtils.hasText(merchantInfoDO.getName())) {
                //     payOrderParamReq.setSubject(merchantInfoDO.getName());
                //     payOrderParamReq.setDescription(merchantInfoDO.getName());
                // }
                // else {
                // }
                payOrderParamReq.setSubject(qrOrderParamReq.getCode()+"码牌收款");
                payOrderParamReq.setDescription(qrOrderParamReq.getCode()+"码牌收款");
            }
            payOrderParamReq.setOrderType(PayOrderEnums.PAY_ORDER_TYPE.QR);
            payOrderParamReq.setRelationOrderNo(merchantQr.getCode());
            PayOrderCommonParamReq.Extra extra = new PayOrderCommonParamReq.Extra();
            extra.setSubAppid(qrOrderParamReq.getAppId());
            extra.setUserId(qrOrderParamReq.getOpenId());
            payOrderParamReq.setExtra(extra);
            payOrderParamReq.setAuthCode(qrOrderParamReq.getAuthCode());
            // payOrderParamReq.setRedirectUrl(redirectUrl);
            log.info("扫码提交订单参数:{}", JsonUtils.toJsonString(payOrderParamReq));
            CommonResult<PayOrderSubmitApiResp> respCommonResult = payOrderAppService.submitOrder(payOrderParamReq);
            // 从新设置登录人信息
            LocalContext.set(localAdminUserRequest);
            return respCommonResult;
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("merchantCharge error:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
        finally {
            // 从新设置登录人信息
            LocalContext.set(localAdminUserRequest);
        }
    }
}
